package define

import (
	"encoding/json"
)

const (
	DefaultVersion = "v0.0.0"

	DefaultUser   = "admin"
	DefaultUserId = "0"
	DefaultPasswd = "admin"
	DefaultGroup  = "Administrator"

	ConfigApplicationLevelGuaranteed = "guaranteed"
	ConfigApplicationLevelBurstAble  = "burstAble"
	ConfigApplicationLevelBestEffort = "bestEffort"

	ConfigStrategyBeatsLevelReadOnly  = "readonly"
	ConfigStrategyBeatsLevelReadWrite = "readwrite"

	ConfigKindApplication = "application"
	ConfigKindStrategy    = "strategy"
	ConfigKindBeats       = "beats"
)

func DynamicStatus() []string {
	return []string{StatusInConfiguration, StatusInScheduling, StatusPending, StatusReady, StatusPause,
		StatusError, StatusTerminating, StatusTerminated}
}

func ConfigApplicationLevels() []string {
	return []string{ConfigApplicationLevelBestEffort, ConfigApplicationLevelBurstAble, ConfigApplicationLevelGuaranteed}
}

func ConfigStrategyLevels() []string {
	return []string{ConfigStrategyBeatsLevelReadOnly, ConfigStrategyBeatsLevelReadWrite}
}

func ConfigKinds() []string {
	return []string{ConfigKindApplication, ConfigKindStrategy, ConfigKindBeats}
}

func ConfigTypes() []string {
	return []string{InstanceTypePod, InstanceTypeContainer}
}

func DefaultConfig() *Config {
	c := Config{}
	c.BaseInfo.Version = DefaultVersion
	c.BaseInfo.Label = "resource.config.xxx"
	c.BaseInfo.Kind = ConfigKindApplication
	c.BaseInfo.Type = InstanceTypeContainer
	c.BaseInfo.Name = "glue name"
	c.BaseInfo.Describe = "glue describe"

	c.UserInfo.UserName = DefaultUser
	c.UserInfo.UserId = DefaultUserId
	c.UserInfo.Group = DefaultGroup
	c.UserInfo.Passwd = DefaultPasswd

	c.SpecInfo.Level = ConfigApplicationLevelBestEffort
	c.SpecInfo.Tags = []Tag{
		{
			Key:   "provider",
			Type:  "string",
			Value: "gluenet",
		},
	}
	c.SpecInfo.ConfigYaml = "{}"

	return &c
}

type Config struct {
	BaseInfo baseInfo `json:"base_info" yaml:"base_info"`
	SpecInfo specInfo `json:"spec_info" yaml:"spec_info"`
	UserInfo userInfo `json:"user_info" yaml:"user_info"`
}

func (r *Config) Clone() *Config {
	c := &Config{
		BaseInfo: r.BaseInfo,
		SpecInfo: r.SpecInfo.Clone(),
		UserInfo: r.UserInfo,
	}
	return c
}

type baseInfo struct {
	Version  string `json:"version" yaml:"version"`
	Kind     string `json:"kind" yaml:"kind"`
	Type     string `json:"type" yaml:"type"`
	Label    string `json:"label" yaml:"label"`
	Name     string `json:"name" yaml:"name"`
	Describe string `json:"describe" yaml:"describe"`
}

type specInfo struct {
	Level      string `json:"level" yaml:"level"`
	Tags       []Tag  `json:"tags" yaml:"tags"`
	ConfigYaml string `json:"config_yaml" yaml:"config_yaml"`
}

func (r specInfo) EnCodeTags() string {
	bts, err := json.Marshal(r.Tags)
	if err != nil {
		panic(err)
	}
	return string(bts)
}
func (r specInfo) DeCodeTags(tags string) {
	if err := json.Unmarshal([]byte(tags), &r.Tags); err != nil {
		panic(err)
	}
}

func (r specInfo) Clone() specInfo {
	tags := make([]Tag, len(r.Tags))
	for k, v := range r.Tags {
		tags[k] = v
	}
	return specInfo{
		Level:      r.Level,
		ConfigYaml: r.ConfigYaml,
		Tags:       tags,
	}
}

type userInfo struct {
	UserName string `json:"user_name" yaml:"user_name"`
	UserId   string `json:"user_id" yaml:"user_id"`
	Passwd   string `json:"passwd" yaml:"passwd"`
	Group    string `json:"group" yaml:"group"`
}
